package com.cy.model;

import com.cy.BasicModel;
import com.cy.ext.plugin.tablebind.TableBind;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.activerecord.Page;
import org.apache.commons.lang3.StringUtils;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@SuppressWarnings("serial")
@TableBind(tableName="point_generated_log",pkName = "id")
public class PointGeneratedLog extends BasicModel<PointGeneratedLog> {
    public static final PointGeneratedLog dao = new PointGeneratedLog();
    public static final String SELECT_ALL = "`id`,`code`,`point_type`,`create_time`,`expire_time`,`first_user_id`,`first_user_name`,`user_id`,`user_name`,`point_num`,`status`";

    @Override
    public Page<PointGeneratedLog> paginate(Integer pageNumber, Integer pageSize, String column, PointGeneratedLog model) {
        List<Object> paras = new ArrayList<>();
        StringBuffer sqlExceptSelectBuffer = new StringBuffer("FROM " + getTableName() + " WHERE 1=1");
        StringBuffer selectBuffer = new StringBuffer("SELECT ").append(column);
        if (pageNumber == null || pageNumber == 0) {
            pageNumber = 1;
        } else {
            pageNumber++;
        }
        if (pageSize == null || pageSize == 0) {
            pageSize = 20;
        }

        if (model != null) {
            String[] attrNames = model.getAttrNames();
            for (String attrName : attrNames) {
                Object attrValue = model.get(attrName);
                if (attrValue != null) {
                    if(attrName.equals("code")){
                        sqlExceptSelectBuffer.append(" AND `code` LIKE ? ");
                        attrValue = "%"+attrValue+"%";
                    }else if(attrName.equals("user_name")){
                        sqlExceptSelectBuffer.append(" AND `user_name` LIKE ? ");
                        attrValue = "%"+attrValue+"%";
                    }else if(attrName.equals("first_user_name")){
                        sqlExceptSelectBuffer.append(" AND `first_user_name` LIKE ? ");
                        attrValue = "%"+attrValue+"%";
                    }else if(attrName.equals("start_create_time")){
                        sqlExceptSelectBuffer.append(" AND `create_time` >= ? ");
                    }else if(attrName.equals("end_create_time")){
                        sqlExceptSelectBuffer.append(" AND `create_time` <= ? ");
                    }else if(attrName.equals("start_expire_time")){
                        sqlExceptSelectBuffer.append(" AND `expire_time` >= ? ");
                    }else if(attrName.equals("end_expire_time")){
                        sqlExceptSelectBuffer.append(" AND `expire_time` <= ? ");
                    }else{
                        sqlExceptSelectBuffer.append(" AND `" + attrName + "`=?");
                    }
                    paras.add(attrValue);
                }
            }
        }

        if (paras.size() > 0) {
            return paginate(pageNumber, pageSize, selectBuffer.toString(), sqlExceptSelectBuffer.toString(), paras.toArray());
        }
        return paginate(pageNumber, pageSize, selectBuffer.toString(), sqlExceptSelectBuffer.toString());
    }

    public PointGeneratedLog findByCode(String code) {
        return this.findFirst("select "+SELECT_ALL+" from point_generated_log where code = ?", code);
    }

    public List<PointGeneratedLog> findByUserIdAndPointTypeAndStatus(Long userId, Integer pointType, Integer status) {
        return this.find("select " + SELECT_ALL + " from point_generated_log where code = ? and point_type = ? and status = ?", userId, pointType, status);
    }

    /**
     * 领取积分(领取系统积分)
     * @param user 用户
     * @param code 兑换码
     */
    public void takePoint(final User user, final String code) {
        Db.tx(new IAtom() {
            @Override
            public boolean run() throws SQLException {
                if (StringUtils.isEmpty(code))
                    throw new RuntimeException("空兑换码");
                PointGeneratedLog pointGeneratedLog = dao.findByCode(code.toUpperCase());
                if (pointGeneratedLog == null)
                    throw new RuntimeException("兑换码无效");
                if (pointGeneratedLog.getStatus() != 0)
                    throw new RuntimeException("兑换码已用过");
                if (new Date().after(pointGeneratedLog.getExpireTime()))
                    throw new RuntimeException("兑换码已过期");
                /*修改状态为已领取*/
                pointGeneratedLog.setStatus(1);
                /*修改所属用户*/
                pointGeneratedLog.setUserId(user.getUserId());
                pointGeneratedLog.setUserName(user.getMobile());
                /*修改第一次所属用户*/
                pointGeneratedLog.setFirstUserId(user.getUserId());
                pointGeneratedLog.setFirstUserName(user.getMobile());
                pointGeneratedLog.update();
                /*增加用户积分*/
                Point point = Point.dao.findByUserAndType(user.getUserId(), pointGeneratedLog.getPointType());
                if(point == null){
                    new Point().setType(pointGeneratedLog.getPointType()).setUserId(user.getUserId()).setPointAvailable(pointGeneratedLog.getPointNum()).setPointFrozen(0L).save();
                } else {
                    point.addPoint(pointGeneratedLog.getPointNum()).update();
                }
                return true;
            }
        });
    }

    /**
     * 转赠积分(转赠未领取积分)
     * @param currUser 当前登录任务
     * @param recordId 生成记录ID
     * @param toAccount 被赠送人
     */
    public void givePoint(final User currUser, final Long recordId, final String toAccount) {
        Db.tx(new IAtom() {
            @Override
            public boolean run() throws SQLException {
                User toUser = User.dao.findByMobile(toAccount);
                if (toUser == null)
                    throw new RuntimeException("唉哟，没有找到该账号呢");
                PointGeneratedLog log = dao.findById(recordId);
                if (log == null)
                    throw new RuntimeException("记录不存在");
                if (log.getStatus() == 0)
                    throw new RuntimeException("积分未领取");
                if (!currUser.getUserId().equals(log.getUserId()))
                    throw new RuntimeException("唉哟，不能再转赠了");
                if (currUser.getMobile().equals(toAccount))
                    throw new RuntimeException("唉哟，不能转赠给自己哦");
                /*赠送人和领取人积分*/
                Point giverPoint = Point.dao.findByUserAndType(currUser.getUserId(), log.getPointType());
                Point takerPoint = Point.dao.findByUserAndType(toUser.getUserId(), log.getPointType());
                /*修改积分所属用户*/
                log.setUserId(toUser.getUserId());
                log.setUserName(toUser.getMobile());
                log.update();

                /*添加积分转赠记录*/
                PointGiveLog pointGiveLog = new PointGiveLog();
                pointGiveLog.setFromUserId(currUser.getUserId());
                pointGiveLog.setFromUserName(currUser.getMobile());
                pointGiveLog.setToUserId(toUser.getUserId());
                pointGiveLog.setToUserName(toUser.getMobile());
                pointGiveLog.setRecordId(recordId);
                pointGiveLog.setCreateTime(new Date());
                try{
                    pointGiveLog.save();
                } catch (Exception e){
                    throw new RuntimeException("该积分已赠送过");
                }

                /*赠送人减分*/
                giverPoint.addPoint(-log.getPointNum());
                giverPoint.update();
                /*领取人加分*/
                if (takerPoint == null){
                    new Point().setType(log.getPointType()).setUserId(log.getUserId()).setPointAvailable(log.getPointNum()).setPointFrozen(0L).save();
                } else {
                    takerPoint.addPoint(log.getPointNum());
                    takerPoint.update();
                }
                return true;
            }
        });
    }

    public void saveBatch(List<PointGeneratedLog> pointGeneratedLogList) {
        String columns = "code,point_type,create_time,expire_time,point_num,status";
        String sql = "INSERT INTO point_generated_log ("+columns+") VALUES (?,?,?,?,?,?)";
        Db.batch(sql, columns, pointGeneratedLogList, 100);
    }

    public PointGeneratedLog setId(Long id){
        return this.set("id",id);
    }

    public Long getId(){
        return this.getLong("id");
    }
        
    public PointGeneratedLog setCode(String code){
        return this.set("code",code);
    }

    public String getCode(){
        return this.getStr("code");
    }
        
    public PointGeneratedLog setPointType(Integer pointType){
        return this.set("point_type",pointType);
    }

    public Integer getPointType(){
        return this.get("point_type");
    }
        
    public PointGeneratedLog setCreateTime(Date createTime){
        return this.set("create_time",createTime);
    }

    public Date getCreateTime(){
        return this.get("create_time");
    }
        
    public PointGeneratedLog setExpireTime(Date expireTime){
        return this.set("expire_time",expireTime);
    }

    public Date getExpireTime(){
        return this.get("expire_time");
    }
        
    public PointGeneratedLog setFirstUserId(Long firstUserId){
        return this.set("first_user_id",firstUserId);
    }

    public Long getFirstUserId(){
        return this.get("first_user_id");
    }
        
    public PointGeneratedLog setFirstUserName(String firstUserName){
        return this.set("first_user_name",firstUserName);
    }

    public String getFirstUserName(){
        return this.getStr("first_user_name");
    }

    public PointGeneratedLog setUserId(Long userId){
        return this.set("user_id",userId);
    }

    public Long getUserId(){
        return this.get("user_id");
    }

    public PointGeneratedLog setUserName(String userName){
        return this.set("user_name",userName);
    }

    public String getUserName(){
        return this.getStr("user_name");
    }

    public PointGeneratedLog setPointNum(Long pointNum){
        return this.set("point_num",pointNum);
    }

    public Long getPointNum(){
        return this.getLong("point_num");
    }

    public PointGeneratedLog setStatus(Integer status){
        return this.set("status",status);
    }

    public Integer getStatus(){
        return this.get("status");
    }

}